//to do:
//	- Ability to cap monster regen? Salt the earth in certain areas?
// fix all the shit that broke with teh new player stats thing
// hook up rng

//future stuff:
//  - moar player state things --> save / load

#include <stdio.h>
#include <assert.h>
#include "game_info.h"
#include "item_costs.h"

player_state g_player_state;



char getInput();
bool process_navigation_input(char userInput);

char getInput()
{
	int input = getc(stdin);

	//if fail to get input, return null
	if (input == EOF)
		return '\0';

	//store 1st char as resulting input
	char result = input;

	//flush out remaining input
	while ((input != EOF) && (input != '\n'))
		input = getc(stdin);

	return result;
}

//	************************
//	*  NAVIGATION ACTIONS  *
//	************************

void monster_intensifies()
{
	printf("The monsters grow stronger.\n\n");
	for (int point_y = 0; point_y < map_size_y; ++point_y)
	{
		// loop over each column of cells
		for (int point_x = 0; point_x < map_size_x; ++point_x)
		{
			if (g_map[point_y][point_x].location != LOCATION_CAMP)
			{
				if (g_map[point_y][point_x].location == LOCATION_CAVE)
				{
					g_map[point_y][point_x].monster += 2;
				}
				else if (g_map[point_y][point_x].location == LOCATION_DEEPS)
				{
					g_map[point_y][point_x].monster += 3;
				}
				else
				{
					++g_map[point_y][point_x].monster;
				}
			}
		}
	}
}


void rest()
{
	t_location map_location = g_map[g_location_y][g_location_x].location;
	if (map_location == LOCATION_CAMP && player_money >= rental_tent_cost)
	{
		printf("You take a rest in a tent and feel much better.\n\n");
		if (player_health <= max_player_health)
		{
			player_money -= rental_tent_cost;
			player_health += rental_tent_heal;
			if (player_health > max_player_health)
			{
				player_health = max_player_health;
			}
		}
	}
	else if (map_location == LOCATION_CAMP && player_money < rental_tent_cost)
	{
		printf("You can't afford that right now.\n\n");
	}
	else
	{
		printf("You can't do that right now.\n\n");
	}
}

void set_camp()
{
	t_location map_location = g_map[g_location_y][g_location_x].location;
	// only allow this if you're not already in a camp tile, have a flag to plant, and no monsters present.
	if (g_map[g_location_y][g_location_x].location != LOCATION_CAMP && flag >= 1 && g_map[g_location_y][g_location_x].monster == 0)
	{
		g_map[g_location_y][g_location_x].location = LOCATION_CAMP;
		printf("You planted a flag. Settlers have established an outpost.\n\n");
		--flag;
	}
	else
	{
		printf("You can't do that right now.\n\n");
	}
}

void buy_potion()
{
	// only allow potion purchase in a camp, and if enough $$
	t_location map_location = g_map[g_location_y][g_location_x].location;
	if (map_location == LOCATION_CAMP && player_money >= potion_cost)
	{
		if (health_potion_count <= max_potion_count)
		{
			++health_potion_count;
			player_money -= potion_cost;
			printf("You purchased one health potion.\n\n");
		}
		else
		{
			printf("Your pockets are already full.\n\n");
		}
	}
	// messaging to show why you couldn't buy that potion because you're too poor.
	else if (map_location == LOCATION_CAMP && player_money < potion_cost)
	{
		printf("You can't afford that potion.\n\n");
	}
	else
	{
		printf("You can't do that right now.\n\n");
	}
}

void buy_flag()
{
	// only allow potion purchase in a camp, and if enough $$
	t_location map_location = g_map[g_location_y][g_location_x].location;
	if (map_location == LOCATION_CAMP && player_money >= flag_cost)
	{
		if (flag == 0)
		{
			++flag;
			player_money -= flag_cost;
			printf("You purchased a flag. You can plant this to establish a new camp.\n\n");
		}
		else
		{
			printf("You can only carry one flag at a time.\n\n");
		}
	}
	// messaging to show why you couldn't buy that potion because you're too poor.
	else if (map_location == LOCATION_CAMP && player_money < flag_cost)
	{
		printf("You can't afford that.\n\n");
	}
	else
	{
		printf("You can't do that right now.\n\n");
	}
}

void training()
{
	t_location map_location = g_map[g_location_y][g_location_x].location;
	if (map_location == LOCATION_CAMP && player_money >= training_cost)
	{
		++player_attack;
	}
	else if (map_location == LOCATION_CAMP && player_money < training_cost)
	{
		printf("You can't afford that right now.\n\n");
	}
	else
	{
		printf("You can't do that here.\n\n");
	}
}

//void monster_info()
//{
//
//	if (g_map[g_location_y][g_location_x].monster > 0)
//	{
//		int monster_health = g_map[g_location_y][g_location_x].monster;
//		printf("There is a monster.\n\n"
//			"( o __ 0)\n\n"
//			"Monster HP: %d.\n\n", g_map[g_location_y][g_location_x].monster);
//	}
//}

void open_chest()
{
	if (g_map[g_location_y][g_location_x].chest == 1 && player_money < max_player_money)
	{
		player_money += 20;
		g_map[g_location_y][g_location_x].chest = 0;
		printf("You discovered a hidden loot chest. You now have %d gold.\n\n", player_money);

		if (player_money > max_player_money)
		{
			player_money = max_player_money;
		}
	}
	else if (player_money == max_player_money)
	{
		printf("There's a chest here, but you can't carry any more gold.\n\n");
	}
}

void attack()
{
	if (g_map[g_location_y][g_location_x].monster > 0)
	{
		g_map[g_location_y][g_location_x].monster -= player_attack;
		player_health -= monster_attack;
		if (g_map[g_location_y][g_location_x].monster > 0)
		{
			printf("You punched the monster. The monster was not pleased, and attacked with his claws.\n"
				"( o __ 0)---E\n\n"
				"--------------------------------------------------------------------------------\n\n");
		}
		else
		{
			player_money += loot_drop;
			if (player_money > max_player_money)
			{
				player_money = max_player_money;
			}
			printf("You killed the monster. His corpse dissolves and leaves %d gold pieces.\n"
				"You now have %d gold.\n\n", loot_drop, player_money);
			open_chest();
		}

	}
	else if (g_map[g_location_y][g_location_x].monster == 0)
	{
		printf("You flail wildly in the air. It does nothing.\n\n");
	}
}

void use_potion()
{
	if (player_health < max_player_health)
		if (health_potion_count >= 1)
		{
			health_potion_count -= 1;
			player_health += 5;
			if (player_health > max_player_health)
			{
				player_health = max_player_health;
			}
		}
		else
		{
			printf("You don't have any health potions to use.\n\n");
		}
	else
	{
		printf("You don't need to heal.\n\n");
	}
}


//	***************************
//	*  PROCESSING USER INPUT  *
//	***************************
bool process_navigation_input(char userInput)
{
	//	 ********************
	//	 *  MOVEMENT INPUT  *
	//	 ********************

	if (userInput == 'w')
	{
		if (g_location_y > 0)
		{
			g_location_y -= 1;
			monster_intensifies();
			return true;
		}
	}
	else if (userInput == 's')
	{
		if (g_location_y < map_size_y - 1)
		{
			g_location_y += 1;
			monster_intensifies();
			return true;
		}
	}
	else if (userInput == 'a')
	{
		if (g_location_x > 0)
		{
			g_location_x -= 1;
			monster_intensifies();
			return true;
		}
	}
	else if (userInput == 'd')
	{
		if (g_location_x < map_size_x - 1)
		{
			g_location_x += 1;
			monster_intensifies();
			return true;
		}
	}
	else if (userInput == 'i')
	{
		location_info();
	}

	//	**************************
	//	*  ACTIONS / ITEM USAGE  *
	//	**************************

	else if (userInput == 'p')
	{
		use_potion();
		return true;
	}
	else if (userInput == 'f')
	{
		attack();
		return true;
	}
	else if (userInput == 'c')
	{
		set_camp();
	}

	//	**********************
	//	*  PURCHASING ITEMS  *
	//	**********************

	else if (userInput == 'b')
	{
		buy_potion();
		return true;
	}
	else if (userInput == 'v')
	{
		buy_flag();
	}
	else if (userInput == 'r')
	{
		rest();
		return true;
	}
	else if (userInput == 'x')
	{
		training();
	}
	else
	{
		printf("That's not a valid input.\n\n");
		return false;
	}
	return false;
}

// **************************
// *  END NAVIGATION STUFF  *
// **************************

void game_intro()
{
	printf("--------------------------------------------------------------------------------\n\n"
			"       You awaken in your hotel room. Use WASD to explore the world. \n\n"
			"                               Controls:\n\n"
			" Move: WASD    Attack: F    Health Potion: P   Set Camp: C    Location Info: I\n\n"
			"                       Buy Flag: v       Buy Potion: B Q\n\n"
			"--------------------------------------------------------------------------------\n\n");
	print_map();
}

void stat_info()
{
	printf("HP: %d    Attack: %d    $: %d    Potion:%d    Flag:%d\n\n", player_health, player_attack, player_money, health_potion_count, flag);
}

void monster_info()
{

        if (g_map[g_location_y][g_location_x].monster > 0)
        { 
                int monster_health = g_map[g_location_y][g_location_x].monster;
                printf("There is a monster.\n\n"
						"( o __ 0)\n\n"
						"Monster HP: %d.\n\n", g_map[g_location_y][g_location_x].monster);
        }
}

void print_map()
{
	printf("\n +-----+-----+-----+-----+\n");
        // loop over each row of cells
        for (int point_y = 0; point_y < map_size_y; ++point_y)
        { 
			printf(" + ");
            // loop over each column of cells
            for (int point_x = 0; point_x < map_size_x; ++point_x)
			{
                 // draw current cell
                 if (point_x == g_location_x && point_y == g_location_y)
                 {
					 printf("@->");
                 }
                 else if (g_map[point_y][point_x].location == LOCATION_CAMP)
                 {
					 printf(" X ");
                 }
				 else if (g_map[point_y][point_x].location == LOCATION_CLIFFS)
                 {
					if (g_map[point_y][point_x].chest > 0)
					{
						printf(" !}");
					}
					else
					{
						printf(" } ");
					}
                 }
				else if (g_map[point_y][point_x].location == LOCATION_FIELD)
                 {
					if (g_map[point_y][point_x].chest > 0)
					{
						printf(" !~");
					}
					else
					{
						printf(" ~ ");
					}

                 }
				 else if (g_map[point_y][point_x].location == LOCATION_CAVE)
                 {
					 if (g_map[point_y][point_x].chest > 0)
					{
						printf(" !c");
					}
					else
					{
						printf(" c ");
					}
                 }
				else if (g_map[point_y][point_x].location == LOCATION_FOREST)
                 {
					 if (g_map[point_y][point_x].chest > 0)
					{
						printf(" !f");
					}
					else
					{
						printf(" f ");
					}
                 }
				 else if (g_map[point_y][point_x].location == LOCATION_DEEPS)
                 {
					 if (g_map[point_y][point_x].chest > 0)
					{
						printf(" !#");
					}
					else
					{
						printf(" # ");
					}
                 }
				else if (g_map[point_y][point_x].location == LOCATION_MOUNTAIN)
                 {
					 if (g_map[point_y][point_x].chest > 0)
					{
						printf("!^^");
					}
					else
					{
						printf("^^ ");
					}
                 }
				 else if (g_map[point_y][point_x].location == LOCATION_VALLEY)
                 {
					if (g_map[point_y][point_x].chest > 0)
					{
						printf("!--");
					}
					else
					{
						printf("-- ");
					}
                 }
				printf(" + ");
            }
		printf("\n +-----+-----+-----+-----+\n");
        }
}


void location_info()
{
        t_location map_location = g_map[g_location_y][g_location_x].location;
        switch (map_location)
        {
        case LOCATION_CAMP:
                printf("You are in a small camp. You can rent a tent to rest for the night for 2 gold.\n\n"
                        "You can purchase a flag to plant, to establish another camp for 30 gold, or buy health \n"
						"potions for 5 gold each.\n\n"
						"You can also train with the swoll swordsman to increase your attack for %d gold.\n\n"
						"--------------------------------------------------------------------------------\n\n"
						"Press R to rest | Press B to buy potions | Press V to buy a flag | Press X to train"
						"--------------------------------------------------------------------------------\n\n", training_cost);
                break;
		case LOCATION_CAVE:
                printf("You enter into a large cave, dimly lit by glowing fungus. It smells faintly of \n"
						"wet dog.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        case LOCATION_CLIFFS:
                printf("You come to the edge of a cliff face.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        case LOCATION_DEEPS:
                printf("You walk ever downwards, deeper into the mountain. Moisture has formed gastly \n"
						"shapes in the rocks, and you grow uneasy.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        case LOCATION_FIELD:
                printf("You are standing in an open field with gently waving grass.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        case LOCATION_FOREST:
                printf("You enter a dark forest. The trees look ancient, and their canopy all but\n"
						"blocks out the sun.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        case LOCATION_MOUNTAIN:
                printf("You are standing at the foot of a large mountain range. The peaks are shrouded \n\n"
						"in fog, and you can see snow high up above the tree line.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        case LOCATION_VALLEY:
                printf("You come to a valley. There is a large gnarled tree off to the north, and a \n"
						"stream runs along the center of the valley.\n\n"
						"There are %d loot chests here.\n\n"
						"--------------------------------------------------------------------------------\n\n", g_map[g_location_y][g_location_x].chest);
                break;
        default:
                //if something not listed do stuff
                break;
        }
}


int main()
{
	g_player_state.dead = false;
	g_player_state.location_x = 0;
	g_player_state.location_y = 0;
	g_player_state.player_health = 20;
	g_player_state.player_money = 10;
	g_player_state.health_potion_count = 0;
	g_player_state.flag = 1;
	g_player_state.player_attack = 1;
	g_player_state.monster_attack = 1;

	game_intro();
	while (!g_player_state.dead)
	{
		assert(g_player_state.location_x >= 0 && g_player_state.location_x < map_size_x);
		assert(g_player_state.location_y >= 0 && g_player_state.location_y < map_size_y);
		
		bool processedInput = false;
		
		while (!processedInput)
		{
			char userInput = getInput();
			printf("--------------------------------------------------------------------------------\n\n");
			processedInput = process_navigation_input(userInput);
			stat_info();
			monster_info();
			print_map();
			if (g_map[g_location_y][g_location_x].location == LOCATION_CAMP)
			{
				printf("\n\n");
				location_info();
			}
		}
		if (player_health == 0)
		{
		        g_dead = true;
		}
	}
	printf("\n\n(X n X)\n\nYou're dead. Good job.");
	getInput();
	getInput();
	return 0;
}